﻿#region Namespace References

using System;
using System.Collections.Generic;
using DynConDevCorp.OpenArch.SmartData.Interfaces;

#endregion

namespace DynConDevCorp.OpenArch.SmartData.Core
{
    public class SmartEntityInstanceGraph
    {
        #region Public Instance Properties

        public IEnumerable<string> CollectionNames
        {
            get { return m_Collections.Keys; }
        }

        #endregion

        #region Public Instance Methods

        /// <summary>
        /// Adds the collection.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="collection">The collection.</param>
        public void AddCollection(string name, ISmartEntityCollection collection)
        {
            List<Guid> entityIDs = new List<Guid>();
            foreach (ISmartEntity entity in collection)
            {
                AddEntityIfNecessary(entity);
                entityIDs.Add(entity.EntityID);
            }
            m_Collections.Add(name, entityIDs);
        }


        /// <summary>
        /// Adds the entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void AddEntity(ISmartEntity entity)
        {
            AddEntityIfNecessary(entity);
        }

        /// <summary>
        /// Gets the collection.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public ISmartEntityCollection<TEntity> GetCollection<TEntity>(string name)
                where TEntity : ISmartEntity, new()
        {
            return GetCollection<SmartEntityCollection<TEntity>, TEntity>(name);
        }

        /// <summary>
        /// Gets the collection.
        /// </summary>
        /// <typeparam name="TCollection">The type of the collection.</typeparam>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public TCollection GetCollection<TCollection,TEntity>(string name)
            where TCollection : SmartEntityCollection<TEntity>, new()
                where TEntity : ISmartEntity, new()
        {
            TCollection retVal = new TCollection();
            List<Guid> entityIDs = m_Collections[name];
            foreach (Guid EntityID in entityIDs)
            {
                ISmartEntity entity;
                if (m_Entities.TryGetValue(EntityID, out entity))
                {
                    retVal.Add((TEntity) entity);
                }
            }
            return retVal;
        }

        /// <summary>
        /// Adds the entity to collection.
        /// </summary>
        /// <param name="collectionName">Name of the collection.</param>
        /// <param name="EntityID">The entity ID.</param>
        public void AddEntityToCollection(string collectionName, Guid EntityID)
        {
            m_Collections[collectionName].Add(EntityID);
        }

        public ISmartEntity GetEntity(Guid entityID)
        {
            //Console.WriteLine("ObjectGraph - Requesting:{0}", entityID);
            return m_Entities[entityID];
        }

        public List<Guid> CollectionEntityIDs(string collectionName)
        {
            return m_Collections[collectionName];
        }

        public List<ISmartEntity> Entities()
        {
            return new List<ISmartEntity>(m_Entities.Values);
        }

        #endregion

        #region Private Instance Methods

        private void AddEntityIfNecessary(ISmartEntity entity)
        {
            Guid entityID = entity.EntityID;
            if (!m_Entities.ContainsKey(entityID))
            {
                //Console.WriteLine("ObjectGraph - REgistering:{0}-{1}",entity.GetType().Name, entityID);
                m_Entities.Add(entityID, entity);
            }
        }

        #endregion

        #region Fields and Constants

        private readonly Dictionary<string, List<Guid>> m_Collections = new Dictionary<string, List<Guid>>();
        private readonly Dictionary<Guid, ISmartEntity> m_Entities = new Dictionary<Guid, ISmartEntity>();

        #endregion
    }
}